package com.perselab.recipe.dao;

import java.io.Serializable;
import java.util.List;

import com.perselab.recipe.bean.Filter;

/**
 * Generic DAO (Data Access Object) with common methods to CRUD POJOs.
 *
 * <p>Extend this interface if you want typesafe (no casting necessary) DAO's for your
 * domain objects.
 *
 * @param <T> a type variable
 * @param <PK> the primary key for that type
 */
public interface GenericDao<T, PK extends Serializable> {
	/**
     * Generic method used to get all objects of a particular type. This
     * is the same as lookup up all rows in a table.
     * @return List of populated objects
     */
    List<T> getAll();

    /**
     * Generic method to get an object based on class and identifier. An
     * ObjectRetrievalFailureException Runtime Exception is thrown if
     * nothing is found.
     *
     * @param id the identifier (primary key) of the object to get
     * @return a populated object
     * @see org.springframework.orm.ObjectRetrievalFailureException
     */
    T get(PK id);

    /**
     * Checks for existence of an object of type T using the id arg.
     * @param id the id of the entity
     * @return - true if it exists, false if it doesn't
     */
    boolean exists(PK id);

    /**
     * Generic method to save an object - handles both update and insert.
     * @param object the object to save
     * @return the persisted object
     */
    T save(T object);

    /**
     * Generic method to delete an object based on class and id
     * @param id the identifier (primary key) of the object to remove
     */
    void remove(PK id);
    
    /**
     * Gets a list of users filters by the parameters.
     * 
     * @param filters This parameter contains a list of Filter elements.
     * A filter is represented from a property name, an operator and a value.
     * The property name can reference a property from a sub-class.
     * For example: user.listInSp. If an alias is missing , like 'profileReviewed'
     * then it's considered that this property belong to the userDetails model.
     * IT'S VERY IMPORTANT TO USE AS ALIAS THE SAME VALUE AS THE CORRESPONDING 
     * PROPERTY FROM UserDetails. 
     * For example to access a Promotional property it would be like this : promotionals.name
     * 
     * 
     * @param sortBy This is the field used  to sort. It must contain the alias also.
     * @param sortOrd The sort order : asc or desc
     * @param start : The index of the first element returned
     * @param maxResults : The total number of results.
     * @return
     */
	public List<T> getFiltered(List<Filter> filters, String sortBy, String sortOrd,final int start, final int maxResults) throws IllegalArgumentException;    

    /**
     * Gets the total number of results based on a set of filters
     * 
     * @param filters This parameter contains a list of Filter elements.
     * A filter is represented from a property name, an operator and a value.
     * The property name can reference a property from a sub-class.
     * For example: user.listInSp. If an alias is missing , like 'profileReviewed'
     * then it's considered that this property belong to the userDetails model.
     * IT'S VERY IMPORTANT TO USE AS ALIAS THE SAME VALUE AS THE CORRESPONDING 
     * PROPERTY FROM UserDetails. 
     * For example to access a Promotional property it would be like this : promotionals.name
     * 
     * 
     * @return
     */	
	public Long getFilteredCount(final List<Filter> filters) throws IllegalArgumentException;
}
